package com.blog4j.article.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blog4j.api.client.FeignSystem;
import com.blog4j.api.client.FeignUser;
import com.blog4j.api.vo.SystemBaseConfigVo;
import com.blog4j.api.vo.UserInfoVo;
import com.blog4j.article.entity.ApplyArticleEntity;
import com.blog4j.article.entity.ArticleEntity;
import com.blog4j.article.mapper.ApplyArticleMapper;
import com.blog4j.article.mapper.ArticleMapper;
import com.blog4j.article.service.ApplyArticleService;
import com.blog4j.article.vo.req.ApplyArticleListReqVo;
import com.blog4j.article.vo.req.ApproveArticleReqVo;
import com.blog4j.article.vo.resp.ApplyArticleRespVo;
import com.blog4j.common.constants.CacheConstants;
import com.blog4j.common.constants.CommonConstant;
import com.blog4j.common.enums.ApproveEnum;
import com.blog4j.common.enums.ArticleStatusEnum;
import com.blog4j.common.enums.ErrorEnum;
import com.blog4j.common.enums.YesOrNoEnum;
import com.blog4j.common.exception.Blog4jException;
import com.blog4j.common.utils.CommonUtil;
import com.blog4j.common.utils.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author 98k灬
 * @version v1.0.0
 * @Description : 功能描述
 * @Create on : 2024/7/23 22:26
 **/
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ApplyArticleServiceImpl extends ServiceImpl<ApplyArticleMapper, ApplyArticleEntity>
        implements ApplyArticleService {
    private final ArticleMapper articleMapper;
    private final FeignUser feignUser;
    private final RedisUtil redisUtil;
    private final FeignSystem feignSystem;
    private final ObjectMapper objectMapper;

    /**
     * 分页加条件查询申请文章信息列表
     *
     * @param reqVo 请求
     * @return 文章信息列表
     */
    @Override
    public PageInfo<ApplyArticleRespVo> applyArticleList(ApplyArticleListReqVo reqVo) {
        String articleTitle = reqVo.getArticleTitle();
        Integer approveStatus = reqVo.getApproveStatus();
        if (Objects.nonNull(approveStatus)) {
            if (!Objects.equals(approveStatus, ApproveEnum.WAIT_APPROVE.getCode()) &&
                    !Objects.equals(approveStatus, ApproveEnum.PASS.getCode()) &&
                    !Objects.equals(approveStatus, ApproveEnum.REJECT.getCode())) {
                throw new Blog4jException(ErrorEnum.INVALID_PARAMETER_ERROR);
            }
        }

        List<ApplyArticleRespVo> applyArticleRespVoList = this.baseMapper.selectApplyArticleList(articleTitle, approveStatus);
        if (CollectionUtil.isEmpty(applyArticleRespVoList)) {
            return new PageInfo<>();
        }

        for (ApplyArticleRespVo respVo : applyArticleRespVoList) {
            String organizationName = respVo.getOrganizationName();
            if (StringUtils.isBlank(organizationName)) {
                continue;
            }
            String[] split = organizationName.split(CommonConstant.COMMA);
            List<String> organizationNameList = Arrays.asList(split);
            respVo.setOrganizationNameList(organizationNameList);
        }

        return new PageInfo<>(applyArticleRespVoList);
    }

    /**
     * 审批文章
     *
     * @param reqVo 审批信息
     */
    @Override
    public void approve(ApproveArticleReqVo reqVo) {
        String articleId = reqVo.getArticleId();
        Integer approveStatus = reqVo.getApproveStatus();
        String approveMessage = reqVo.getApproveMessage();
        ArticleEntity article = this.beforeApprove(articleId, approveStatus, approveMessage);

        String userId = StpUtil.getLoginIdAsString();
        UserInfoVo userInfoVo = feignUser.getUserInfoByUserId(userId);
        article.setApproveStatus(approveStatus)
                .setApproveUserId(userId)
                .setApproveUserName(userInfoVo.getUserName())
                .setApproveTime(CommonUtil.getCurrentDateTime())
                .setApproveMessage(approveMessage)
                .setStatus(ArticleStatusEnum.WAIT.getCode());
        articleMapper.updateById(article);

        SystemBaseConfigVo systemBaseConfig = this.getSystemBaseConfig();
        if (Objects.equals(YesOrNoEnum.YES.getCode(), systemBaseConfig.getApproveArticleOpenEmailNotify())) {
            // 异步邮件通知作者审批通过
        }
    }

    // =================== private ================================================================

    private SystemBaseConfigVo getSystemBaseConfig()  {
        Object val = redisUtil.get(CacheConstants.SYSTEM_BASE_CONFIG_KEY);
        if (Objects.isNull(val)) {
            return feignSystem.getBaseSystemConfig();
        }

        try {
            JSONArray jsonArray = JSON.parseArray((String) val);
            JSONObject jsonObject = JSON.parseObject(objectMapper.writeValueAsString(jsonArray.get(1)));
            return JSON.toJavaObject(jsonObject, SystemBaseConfigVo.class);
        } catch (Exception exception) {
            throw new Blog4jException(ErrorEnum.PARSE_ERROR);
        }
    }

    private ArticleEntity beforeApprove(String articleId, Integer approveStatus, String approveMessage) {
        if (!Objects.equals(ApproveEnum.PASS.getCode(), approveStatus) &&
                !Objects.equals(ApproveEnum.REJECT.getCode(), approveStatus)) {
            throw new Blog4jException(ErrorEnum.APPROVE_STATUS_ERROR);
        }

        if (Objects.equals(ApproveEnum.REJECT.getCode(), approveStatus) &&
                StringUtils.isBlank(approveMessage)) {
            throw new Blog4jException(ErrorEnum.APPROVE_REJECT_MESSAGE_ERROR);
        }

        ArticleEntity article = articleMapper.selectById(articleId);
        if (Objects.isNull(article)) {
            throw new Blog4jException(ErrorEnum.ARTICLE_NOT_EXIST_ERROR);
        }

        if (!Objects.equals(article.getStatus(), ArticleStatusEnum.WAIT.getCode())) {
            throw new Blog4jException(ErrorEnum.INVALID_PARAMETER_ERROR);
        }

        if (!Objects.equals(article.getApproveStatus(), ApproveEnum.WAIT_APPROVE.getCode())) {
            throw new Blog4jException(ErrorEnum.INVALID_PARAMETER_ERROR);
        }

        LambdaQueryWrapper<ApplyArticleEntity> wrapper = new LambdaQueryWrapper<ApplyArticleEntity>()
                .eq(ApplyArticleEntity::getArticleId, articleId);
        ApplyArticleEntity applyArticle = this.baseMapper.selectOne(wrapper);
        if (Objects.isNull(applyArticle)) {
            throw new Blog4jException(ErrorEnum.APPROVE_ARTICLE_NOT_EXIST_ERROR);
        }

        return article;
    }
}
